#include "Wrapper.hpp"
#include "polyTask.hpp"
#include "TupleHelper.hpp"
#include "TaskTag.hpp"
#include "definitions.h"

#include "tbb/tick_count.h"

template <int TASK_ID, int NPARAMS, int TASKTAGDIM, int INTERTASKDIM>
void PolyTask<TASK_ID, NPARAMS, TASKTAGDIM, INTERTASKDIM>::operator()() {
  polyTask_context<TASK_ID, TASKTAGDIM, INTERTASKDIM> c;

#ifdef DEBUG
  CnC::debug::collect_scheduler_statistics( c );
  CnC::debug::trace( c.m_tags );
  CnC::debug::trace( c.M );
#endif //DEBUG   

  tbb::tick_count tick = tbb::tick_count::now();

  {
    const int pT = params[0];
    const int pM = params[1];
    const int pN = params[2];
    const int pP = params[3];
    c.M.put(TaskTag<TASK_ID, TASKTAGDIM, INTERTASKDIM>
            (toArray(makeIdenticalTuple<int64_t, TASKTAGDIM>::make(ZERO_TASK_INDEX))), M);

#include "definitions.h"
    int64_t t1, t2, t3;
    for (t1=ceild(-pN-15,16);t1<=floord(pT-3,16);t1++) {
      for (t2=max(t1,-t1-1);
           t2<=min(min(floord(-8*t1+pT-2,8),floord(8*t1+pN+7,8)),floord(pT+pN-2,16));t2++) {
        for (t3=max(max(0,ceild(t1+t2-1,2)),ceild(16*t2-pN-14,16));
             t3<=min(min(floord(pT+pN-2,16),floord(16*t2+pN+14,16)),floord(8*t1+8*t2+pN+15,16));
             t3++) {
          c.m_tags.put(TaskTag<TASK_ID, TASKTAGDIM, INTERTASKDIM>(t1, t2, t3,  pT,  pM,  pN, pP));
        }
      }
    }
    // Wait for all steps to finish
    c.wait();

    printf("Total time for init and parallel execution of %d iterations of a" \
           "polyTask of size %d x %d x %d: %g sec\n", 
           pT, pN, pN, pN, (tbb::tick_count::now()-tick).seconds());
  }
}

// Template instantiation
template void PolyTask<0, 4, TASKTAGDIMMACRO, INTERTASKDIMMACRO>::operator()();
